package com.community.sqlapp.service;

import com.google.gson.*;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.file.Files;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedHashMap;

/**
 * xmind解析生成xmind文件实现类
 */
@Service
public class TestPointConverService {
    private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();

    /**
     * 递归将任意JSON结构转为XMind树结构
     * 支持 {"测试点": [...] } 这种结构，所有分层、子测试点、测试方法都能还原为XMind节点
     */
    public static String jsonToXmindTree(String json) {
        JsonElement rootElem = JsonParser.parseString(json);
        JsonObject rootObj;
        if (rootElem.isJsonObject()) {
            rootObj = rootElem.getAsJsonObject();
        } else {
            throw new IllegalArgumentException("输入必须为JSON对象");
        }
        // 取第一个key作为根节点
        Set<Map.Entry<String, JsonElement>> entries = rootObj.entrySet();
        if (entries.isEmpty()) throw new IllegalArgumentException("JSON对象不能为空");
        Map.Entry<String, JsonElement> first = entries.iterator().next();
        JsonObject xmindRoot = new JsonObject();
        xmindRoot.addProperty("topic", first.getKey());
        JsonArray children = new JsonArray();
        buildXmindChildren(first.getValue(), children);
        if (children.size() > 0) xmindRoot.add("children", children);
        return gson.toJson(xmindRoot);
    }

    // 递归构建children，增强适配多层级结构
    private static void buildXmindChildren(JsonElement elem, JsonArray children) {
        if (elem == null || elem.isJsonNull()) return;
        if (elem.isJsonArray()) {
            for (JsonElement e : elem.getAsJsonArray()) {
                buildXmindChildren(e, children);
            }
        } else if (elem.isJsonObject()) {
            JsonObject obj = elem.getAsJsonObject();
            String topic = null;
            JsonArray nodeChildren = new JsonArray();

            // 优先常规字段
            if (obj.has("一级模块")) {
                topic = obj.get("一级模块").isJsonPrimitive() ? obj.get("一级模块").getAsString() : "一级模块";
                if (obj.has("二级模块")) {
                    buildXmindChildren(obj.get("二级模块"), nodeChildren);
                }
            } else if (obj.has("二级模块")) {
                if (obj.get("二级模块").isJsonArray()) {
                    topic = null;
                    buildXmindChildren(obj.get("二级模块"), nodeChildren);
                } else if (obj.get("二级模块").isJsonPrimitive()) {
                    topic = obj.get("二级模块").getAsString();
                    if (obj.has("测试点")) {
                        buildXmindChildren(obj.get("测试点"), nodeChildren);
                    }
                } else if (obj.get("二级模块").isJsonObject()) {
                    topic = "二级模块";
                    buildXmindChildren(obj.get("二级模块"), nodeChildren);
                }
            } else if (obj.has("测试点")) {
                JsonElement testPointElem = obj.get("测试点");
                if (testPointElem.isJsonArray()) {
                    topic = "测试点";
                    buildXmindChildren(testPointElem, nodeChildren);
                } else if (testPointElem.isJsonPrimitive()) {
                    topic = testPointElem.getAsString();
                    if (obj.has("测试用例名称")) {
                        buildXmindChildren(obj.get("测试用例名称"), nodeChildren);
                    }
                } else if (testPointElem.isJsonObject()) {
                    topic = "测试点";
                    buildXmindChildren(testPointElem, nodeChildren);
                }
            } else if (obj.has("测试用例名称")) {
                topic = obj.get("测试用例名称").isJsonPrimitive() ? obj.get("测试用例名称").getAsString() : "测试用例名称";
            } else if (obj.has("名称")) {
                topic = obj.get("名称").isJsonPrimitive() ? obj.get("名称").getAsString() : "名称";
            } else if (obj.has("topic")) {
                topic = obj.get("topic").isJsonPrimitive() ? obj.get("topic").getAsString() : "topic";
            } else {
                // 新增：如果是普通对象，遍历所有key，每个key作为一个子节点
                for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
                    String key = entry.getKey();
                    JsonElement value = entry.getValue();
                    JsonObject node = new JsonObject();
                    node.addProperty("topic", key);
                    JsonArray childArr = new JsonArray();
                    if (value.isJsonArray() || value.isJsonObject()) {
                        buildXmindChildren(value, childArr);
                        if (childArr.size() > 0) node.add("children", childArr);
                    } else if (value.isJsonPrimitive()) {
                        // 叶子节点直接显示key: value
                        node.addProperty("topic", key + ": " + value.getAsString());
                    }
                    children.add(node);
                }
                return;
            }

            // 只在有topic时生成节点
            if (topic != null) {
                JsonObject node = new JsonObject();
                node.addProperty("topic", topic);
                if (nodeChildren.size() > 0) node.add("children", nodeChildren);
                children.add(node);
            } else if (nodeChildren.size() > 0) {
                for (JsonElement c : nodeChildren) {
                    children.add(c);
                }
            }
        } else if (elem.isJsonPrimitive()) {
            JsonObject node = new JsonObject();
            node.addProperty("topic", elem.getAsString());
            children.add(node);
        }
    }

    /**
     * 将平铺的数组结构自动分层为树状结构，支持一级模块、二级模块、测试点、测试用例名称四级分组
     */
    public static String flatJsonToXmindTree(String json) {
        JsonElement elem = JsonParser.parseString(json);
        if (elem.isJsonArray()) {
            JsonArray arr = elem.getAsJsonArray();
            // 构建树：Map<一级, Map<二级, Map<测试点, List<测试用例名称>>>>
            Map<String, Map<String, Map<String, List<String>>>> tree = new LinkedHashMap<>();
            for (JsonElement e : arr) {
                JsonObject obj = e.getAsJsonObject();
                String lv1 = obj.has("一级模块") ? obj.get("一级模块").getAsString() : "未知一级";
                String lv2 = obj.has("二级模块") ? obj.get("二级模块").getAsString() : "未知二级";
                // 处理测试点为数组或字符串
                List<String> testPoints = new ArrayList<>();
                if (obj.has("测试点")) {
                    JsonElement tpElem = obj.get("测试点");
                    if (tpElem.isJsonArray()) {
                        for (JsonElement tp : tpElem.getAsJsonArray()) {
                            testPoints.add(tp.getAsString());
                        }
                    } else if (tpElem.isJsonPrimitive()) {
                        testPoints.add(tpElem.getAsString());
                    }
                } else {
                    testPoints.add("未知测试点");
                }
                // 处理测试用例名称为数组或字符串
                List<String> caseNames = new ArrayList<>();
                if (obj.has("测试用例名称")) {
                    JsonElement cnElem = obj.get("测试用例名称");
                    if (cnElem.isJsonArray()) {
                        for (JsonElement cn : cnElem.getAsJsonArray()) {
                            caseNames.add(cn.getAsString());
                        }
                    } else if (cnElem.isJsonPrimitive()) {
                        caseNames.add(cnElem.getAsString());
                    }
                } else {
                    caseNames.add("用例");
                }
                // 构建树结构
                for (int i = 0; i < Math.max(testPoints.size(), caseNames.size()); i++) {
                    String lv3 = i < testPoints.size() ? testPoints.get(i) : "未知测试点";
                    String lv4 = i < caseNames.size() ? caseNames.get(i) : "用例";
                    tree.computeIfAbsent(lv1, k -> new LinkedHashMap<>())
                            .computeIfAbsent(lv2, k -> new LinkedHashMap<>())
                            .computeIfAbsent(lv3, k -> new ArrayList<>())
                            .add(lv4);
                }
            }
            // 构建XMind JSON
            JsonObject root = new JsonObject();
            root.addProperty("topic", "一级目录");
            JsonArray lv1Arr = new JsonArray();
            for (Map.Entry<String, Map<String, Map<String, List<String>>>> e1 : tree.entrySet()) {
                JsonObject lv1Node = new JsonObject();
                lv1Node.addProperty("topic", e1.getKey());
                JsonArray lv2Arr = new JsonArray();
                for (Map.Entry<String, Map<String, List<String>>> e2 : e1.getValue().entrySet()) {
                    JsonObject lv2Node = new JsonObject();
                    lv2Node.addProperty("topic", e2.getKey());
                    JsonArray lv3Arr = new JsonArray();
                    for (Map.Entry<String, List<String>> e3 : e2.getValue().entrySet()) {
                        JsonObject lv3Node = new JsonObject();
                        lv3Node.addProperty("topic", e3.getKey());
                        JsonArray lv4Arr = new JsonArray();
                        for (String lv4 : e3.getValue()) {
                            JsonObject lv4Node = new JsonObject();
                            lv4Node.addProperty("topic", lv4);
                            lv4Arr.add(lv4Node);
                        }
                        if (lv4Arr.size() > 0) lv3Node.add("children", lv4Arr);
                        lv3Arr.add(lv3Node);
                    }
                    if (lv3Arr.size() > 0) lv2Node.add("children", lv3Arr);
                    lv2Arr.add(lv2Node);
                }
                if (lv2Arr.size() > 0) lv1Node.add("children", lv2Arr);
                lv1Arr.add(lv1Node);
            }
            if (lv1Arr.size() > 0) root.add("children", lv1Arr);
            return gson.toJson(root);
        } else if (elem.isJsonObject()) {
            // 新增：对象结构直接用递归树方法
            return jsonToXmindTree(json);
        } else {
            throw new IllegalArgumentException("不支持的JSON结构");
        }
    }

    /**
     * 生成xmind8文件（包含content.xml和META-INF/manifest.xml，标准结构）
     */
    public static void generateXMind(String json, String outputPath) throws Exception {
        String contentXml = jsonToXMindContentXml(json);
        // 1. 生成content.xml
        File tempDir = new File("temp_xmind");
        if (!tempDir.exists()) tempDir.mkdirs();
        File contentFile = new File(tempDir, "content.xml");
        try (FileOutputStream fos = new FileOutputStream(contentFile)) {
            fos.write(contentXml.getBytes("UTF-8"));
        }
        // 2. 生成META-INF/manifest.xml
        File metaInfDir = new File(tempDir, "META-INF");
        if (!metaInfDir.exists()) metaInfDir.mkdirs();
        File manifestFile = new File(metaInfDir, "manifest.xml");
        String manifestXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
                "<manifest xmlns=\"urn:xmind:xmap:xmlns:manifest:1.0\">\n" +
                "  <file-entry full-path=\"content.xml\" media-type=\"text/xml\"/>\n" +
                "</manifest>\n";
        try (FileOutputStream fos = new FileOutputStream(manifestFile)) {
            fos.write(manifestXml.getBytes("UTF-8"));
        }
        // 3. 打包为zip（xmind）
        try (FileOutputStream fos = new FileOutputStream(outputPath);
             ZipOutputStream zos = new ZipOutputStream(fos)) {
            // content.xml
            ZipEntry entry1 = new ZipEntry("content.xml");
            zos.putNextEntry(entry1);
            byte[] bytes1 = Files.readAllBytes(contentFile.toPath());
            zos.write(bytes1, 0, bytes1.length);
            zos.closeEntry();
            // META-INF/manifest.xml
            ZipEntry entry2 = new ZipEntry("META-INF/manifest.xml");
            zos.putNextEntry(entry2);
            byte[] bytes2 = Files.readAllBytes(manifestFile.toPath());
            zos.write(bytes2, 0, bytes2.length);
            zos.closeEntry();
        }
        // 清理临时文件
        contentFile.delete();
        manifestFile.delete();
        metaInfDir.delete();
        tempDir.delete();
    }

    // 将json结构转为xmind8 content.xml内容（极简结构，仅topic树）
    private static String jsonToXMindContentXml(String json) {
        JsonObject root = gson.fromJson(json, JsonObject.class);
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
        sb.append("<xmap-content xmlns=\"urn:xmind:xmap:xmlns:content:2.0\" version=\"2.0\">\n");
        sb.append("  <sheet id=\"1\" timestamp=\"" + System.currentTimeMillis() + "\">\n");
        sb.append("    <title>").append(root.get("topic").getAsString()).append("</title>\n");
        sb.append(jsonTopicToXml(root, 3));
        sb.append("  </sheet>\n");
        sb.append("</xmap-content>\n");
        return sb.toString();
    }

    private static String jsonTopicToXml(JsonObject node, int indent) {
        StringBuilder sb = new StringBuilder();
        String topic = node.has("topic") ? node.get("topic").getAsString() : "";
        String pad = "  ".repeat(indent);
        sb.append(pad).append("<topic id=\"t" + System.nanoTime() + "\">\n");
        sb.append(pad).append("  <title>").append(topic).append("</title>\n");
        if (node.has("children")) {
            JsonArray children = node.getAsJsonArray("children");
            if (children.size() > 0) {
                sb.append(pad).append("  <children>\n");
                sb.append(pad).append("    <topics type=\"attached\">\n");
                for (int i = 0; i < children.size(); i++) {
                    JsonObject child = children.get(i).getAsJsonObject();
                    sb.append(jsonTopicToXml(child, indent + 3));
                }
                sb.append(pad).append("    </topics>\n");
                sb.append(pad).append("  </children>\n");
            }
        }
        sb.append(pad).append("</topic>\n");
        return sb.toString();
    }
}